//
//  GameViewController.swift
//  Yidingzhi
//
//  Created by flybywind on 15/11/22.
//  Copyright (c) 2015年 flybywind. All rights reserved.
//

import UIKit
import QuartzCore
import SceneKit
import SpriteKit


class GameViewController: UIViewController, OptionDelegate, ToolBarDelegate {

    // MARK: properties
    var suitStatus = SuitStatus()
    var rotate3D: Rotate3D = Rotate3D(rx: 0, ry: 0, rz: 0,
        maxRx: Float(0.15*M_PI), maxRy: 0, maxRz: 0)
    var geometryNode: SCNNode!
    var cameraNode : SCNNode!
    var textureMaterial : SCNMaterialProperty?
    var textureList : UITableView?
    var optionHeight:Double = 0
    var toolBarItem = [ToolBarBtn]()
    var dressComposite = ["西服": DressComposite(parts_list: ["种类", "衣领"]),
        "衬衫": DressComposite(parts_list: ["种类"])]
    // MARK: constants
    
    let textGold = UIColor(red: CGFloat(254.0/255),
            green: CGFloat(234.0/255), blue: CGFloat(185.0/255), alpha: 1)
    let blueBack = UIColor(red: 0,
        green: CGFloat(53.0/255), blue: CGFloat(82.0/255), alpha: 1)
    let textRed = UIColor(red: CGFloat(204.0/255),
            green: CGFloat(20.0/255), blue: CGFloat(29.0/255), alpha: 1)
    let dressTypeList = ["西服", "衬衫"]
    let toolBarList = ["种类", "选款式", "选面料"]
//    let allDingzhiOption = [
//        "yiling": ["平驳领", "青果领"],
//        "衬衫领": ["平角领", "大角领", "小角领", "中山领", "元宝领"],
//        "排扣":   ["单排扣", "2粒双排扣", "3粒双排扣"],
//        "下摆":   ["平角", "圆角"],
//        "开襟":   ["单", "双"],
//        "裤褶":   ["单", "双"],
//        "袖子":   ["平角","圆角","截角","大圆角"]
//        ]
    let StylePopup : [String: [String: OptionsWrapper]] = [
        "西服": ["yiling": OptionsWrapper(alertTitle: "衣领", options: ["平驳领", "青果领"])],
    ]
    let allowTexture : [String: Set<String>] = [
        "西服": ["xizhuang", "kuzi", "chenshan", "lingdai"],
        "衬衫": ["chenshan", "kuzi", "lingdai"]]
    
    let sourcePath = NSBundle.mainBundle()
    // MARK: viewDidLoad
    override func viewDidLoad() {
        super.viewDidLoad()
        dressComposite["西服"]!.setAllParts(["西服", "青果领"])
        dressComposite["衬衫"]!.setAllParts(["衬衫"])
        // create a new scene
        let scene = SCNScene()
        
        // create and add a camera to the scene
        cameraNode = SCNNode()
        cameraNode.camera = SCNCamera()
        cameraNode.camera?.automaticallyAdjustsZRange = true;
        scene.rootNode.addChildNode(cameraNode)
        // place the camera
        cameraNode.position = SCNVector3(x: 0, y: 500, z: 1000)
        
        // create and add a light to the scene
        let lightNode = SCNNode()
        lightNode.light = SCNLight()
        lightNode.light!.type = SCNLightTypeAmbient
        lightNode.light!.color = UIColor.whiteColor()
        lightNode.position = SCNVector3(x: 0, y: 0, z: 0)
        scene.rootNode.addChildNode(lightNode)
        
        // create and add an ambient light to the scene
        let dirLightNode = SCNNode()
        dirLightNode.light = SCNLight()
        dirLightNode.light!.type = SCNLightTypeDirectional
        dirLightNode.light!.color = UIColor.whiteColor()
        dirLightNode.transform = SCNMatrix4MakeRotation(-45, 1, 0, 0)
        dirLightNode.position = SCNVector3Make(0, 1000, 400)
        scene.rootNode.addChildNode(dirLightNode)
        
        // retrieve the SCNView
        let scnView = self.view as! SCNView
        
        // set the scene to the view
        scnView.scene = scene
        // show statistics such as fps and timing information
        scnView.showsStatistics = true
        // retrieve the ship node
        loadSceneByName(dressComposite[suitStatus.dressType]!.getFullName())
        
        // add a tap gesture recognizer
        let tapGesture = UITapGestureRecognizer(target: self, action: "handleTap:")
        let panGesture = UIPanGestureRecognizer(target: self, action: "handlePan:")
        let pinchGesture = UIPinchGestureRecognizer(target: self, action: "handlePinch:")
        scnView.addGestureRecognizer(tapGesture)
        scnView.addGestureRecognizer(panGesture)
        scnView.addGestureRecognizer(pinchGesture)


        setupToolBar()
    }
    func loadSceneByName(scnNameOpt: String?) {
        if let scnName = scnNameOpt {
            let scnView = self.view as! SCNView
            
            let scene = scnView.scene!
            
            if let scene_new = SCNScene(named: "art.scnassets/\(scnName).scn") {
                let new_node = scene_new.rootNode.childNodeWithName("model", recursively: true)
                if let old_node = scene.rootNode.childNodeWithName("model", recursively: true) {
                    old_node.removeFromParentNode()
                }
                if new_node != nil {
                    scene.rootNode.addChildNode(new_node!)
                    geometryNode = new_node
                }
            } else {
                log.debug("no such sceen: \(scnName).scn!")
            }
        }else {
            log.debug("scene name is nil")
        }
    }
    // MARK: options
    func setupToolBar() {
        let toolBarInfo = ["", "style", "fabric"]
        let screenWidth = self.view!.frame.width
        let optionNum = toolBarList.count
        let scnView = self.view!
        let blockWidth = Double(screenWidth)/(Double(optionNum))
        let optionWidth = blockWidth*0.8
        let optionGap = blockWidth*0.1
        optionHeight = min(optionWidth*0.5, 30.0)
                
        
        for i in 0..<optionNum {
            let rect = CGRect(x: blockWidth*(Double(i)) + optionGap,
                y: 10.0, width: optionWidth, height: optionHeight)
            let btn = ToolBarBtn(frame: rect, title: toolBarList[i], info: toolBarInfo[i], borderColor: blueBack, backColor: UIColor.whiteColor(),
                borderColor2: textGold, backColor2: blueBack)
            if i == 0 {
                btn.optionList = OptionsWrapper(alertTitle: toolBarList[i],
                    options: dressTypeList)
            }
            toolBarItem.append(btn)
            
            if i == 1 {
                btn.setActive()
            }
            btn.addTarget(self, forControlEvents: .TouchUpInside)
            scnView.addSubview(btn)
        }
    }
    
    // MARK: textures
    func setTextureOn(destPart:String, texture2D texture:UIImage?, textureScale: Float) {
        if texture == nil {
            log.debug("no texture!")
            return
        }
        let part = geometryNode.childNodeWithName(destPart, recursively: true)!
        if part.geometry!.firstMaterial == nil {
            log.debug("creat new material!")
            part.geometry!.firstMaterial = SCNMaterial()
        }
        let fm = part.geometry!.firstMaterial!
        
        fm.diffuse.contentsTransform = SCNMatrix4MakeScale(textureScale, textureScale, 1.0)
        fm.diffuse.contents = texture
        fm.diffuse.wrapT = .Mirror
        fm.diffuse.wrapS = .Mirror
    }
    
    func getTexture(textName:String) ->UIImage? {
        if let imagFile = sourcePath.pathForResource(textName,
                ofType: "jpg") {
            let imageTexture = UIImage(contentsOfFile: imagFile)
            
            return imageTexture
        } else {
            log.debug("cant find \(textName) in source. \(sourcePath.bundlePath)")
            return nil
        }

    }
    
    // MARK: gesture
    func handleTap(gestureRecognize: UITapGestureRecognizer) {
        let scnView = self.view as! SCNView
        // check what nodes are tapped
        let p = gestureRecognize.locationInView(scnView)
        let hitResults = scnView.hitTest(p, options: nil)
        var showFabric = false
        // check that we clicked on at least one object
        if hitResults.count > 0 {
            // retrieved the first clicked object
            let result: AnyObject! = hitResults[0]
            
            // get its material
            let tapedMaterial = result.node!.geometry!.firstMaterial
            if tapedMaterial != nil {
                suitStatus.selectPart = result.node!.name?.componentsSeparatedByString("-")[0];
                log.debug("select part: \(suitStatus.selectPart)")
                if suitStatus.mode == "fabric" {
                    if allowTexture[suitStatus.dressType]!.contains(suitStatus.selectPart!) {
                        showFabric = true
                    }else {
                        log.debug("\(suitStatus.selectPart) no fabric for selection")
                    }
                } else if suitStatus.mode == "style" {
                    if let typePopup = StylePopup[suitStatus.dressType]{
                        if let alert = typePopup[suitStatus.selectPart!] {
                            alert.popUpBy(self)
                        }
                    }
                }
            }else{
                log.debug("没有设置material！")
            }
        }
        
        let container = parentViewController! as! ContainerViewController
        if showFabric {
            container.showFabric(suitStatus)
        } else {
            container.hideFabric()
        }

    }
    func afterSelectFabric(receiveData: SuitStatus) {
        log.debug("receive image, render texture \(receiveData.selectFabric) on \(suitStatus.selectPart!)")
        self.setTextureOn(suitStatus.selectPart!, texture2D: receiveData.selectFabric, textureScale: receiveData.fabricScale)
        
    }
    func handlePinch(gestureRecognize: UIPinchGestureRecognizer) {
        let scale = Float(gestureRecognize.scale)
        var depth = cameraNode.position.z
        depth += (50*(scale-1))
        cameraNode.position.z = depth
    }
    func handlePan(gestureRecognize: UIPanGestureRecognizer) {
        let pan = gestureRecognize.translationInView(self.view)
        let ry = (Float)(pan.x/10) * (Float)(M_PI/180.0)
        let rx = (Float)(pan.y/50) * (Float)(M_PI/180.0)
        rotate3D.rotate3DAdd(rotX: rx, rotY: ry, rotZ: 0)
        let rotMat = rotate3D.rotate3DMatrix()
        geometryNode.transform = SCNMatrix4Translate(rotMat,
            geometryNode.position.x, geometryNode.position.y,
            geometryNode.position.z)
    }
    // 按照比例移动, 屏幕左右边缘分别为-0.5和0.5
    func moveModelHorizontal(var xlocRatio: Float, animDuration: Double) {
        if xlocRatio > 1 {
            xlocRatio = 1
        }
        if xlocRatio < 0 {
            xlocRatio = 0
        }

        let width = self.view!.frame.width
        let xloc = Float(width) * xlocRatio
        
        SCNTransaction.setAnimationDuration(CFTimeInterval(animDuration))
        SCNTransaction.begin()
        geometryNode.position.x = xloc
        SCNTransaction.setCompletionBlock{
            SCNTransaction.setAnimationDuration(CFTimeInterval(0))
        }
        SCNTransaction.commit()
    }
    func resetModelHorizontal(animDuration:Double) {
        SCNTransaction.setAnimationDuration(CFTimeInterval(animDuration))
        SCNTransaction.begin()
        geometryNode.position.x = 0
        SCNTransaction.setCompletionBlock{
            SCNTransaction.setAnimationDuration(CFTimeInterval(0))
        }
        SCNTransaction.commit()
        
    }
    
    // MARK: delegate
    func afterSelect(optionWrapper:OptionsWrapper) {
        log.debug("select \(optionWrapper.title) ==> \(optionWrapper.selectedOption)")

        if optionWrapper.title == "种类" {
            suitStatus.dressType = optionWrapper.selectedOption
        } else {
            let partName = optionWrapper.title
            let partValue = optionWrapper.selectedOption
            dressComposite[suitStatus.dressType]?.setParts(partName, value: partValue)
        }
        let scnName = dressComposite[suitStatus.dressType]?.getFullName()
        loadSceneByName(scnName)
    }
    func toolBarTaped(btn:ToolBarBtn) {
        if btn.optionList != nil {
            btn.optionList?.popUpBy(self)
        } else {
            self.suitStatus.mode = btn.info
            for b in toolBarItem {
                if b.optionList == nil {
                    b.setNormal()
                }
            }
            btn.setActive()
        }
    }
    
    
    // MARK: override
    override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
        geometryNode.transform = SCNMatrix4MakeScale(0.99, 1,1)
        SCNTransaction.begin()
        geometryNode.transform = SCNMatrix4Identity
        SCNTransaction.commit()
        
        let screenWidth = size.width
        let optionNum = toolBarItem.count
        let blockWidth = Double(screenWidth)/(Double(optionNum))
        let optionWidth = blockWidth*0.8
        let optionGap = blockWidth*0.1
        optionHeight = min(optionWidth*0.5, 30.0)
        
        for (i, btn) in toolBarItem.enumerate() {
            let rect = CGRect(x: blockWidth*(Double(i)) + optionGap,
                y: 10.0, width: optionWidth, height: optionHeight)
            btn.resetFrame(rect)
            log.debug("for [\(i)]: origin:\(btn.frame.origin), size: \(btn.frame.size)")
        }
    }
    override func shouldAutorotate() -> Bool {
        return true
    }
    
    override func prefersStatusBarHidden() -> Bool {
        return true
    }
    
    override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
        if UIDevice.currentDevice().userInterfaceIdiom == .Phone {
            return .AllButUpsideDown
        } else {
            return .All
        }
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Release any cached data, images, etc that aren't in use.
    }

}
